package com.kamistoat.meimeimall.meimeimallauthserver.service.impl;

import com.kamistoat.meimeimall.common.To.EsTo.RegisterUpTo;
import com.kamistoat.meimeimall.common.To.memberTo.RegisterMemberTo;
import com.kamistoat.meimeimall.common.constant.AuthConstant;
import com.kamistoat.meimeimall.common.constant.ThirdPartyConstant;
import com.kamistoat.meimeimall.common.dubboInterface.MemberDubboInterface;
import com.kamistoat.meimeimall.common.dubboInterface.SearchDubboInterface;
import com.kamistoat.meimeimall.common.dubboInterface.ThirdPartyDubboInterface;
import com.kamistoat.meimeimall.common.exception.BizCodeEnum;
import com.kamistoat.meimeimall.common.exception.RRException;
import com.kamistoat.meimeimall.common.utils.R;
import com.kamistoat.meimeimall.meimeimallauthserver.service.AuthService;
import com.kamistoat.meimeimall.meimeimallauthserver.vo.UserRegisterVo;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.UUID;

@Service("authService")
public class AuthServiceImpl implements AuthService {
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Reference
    MemberDubboInterface memberDubboInterface;
    @Reference
    SearchDubboInterface searchDubboInterface;
    @Reference
    ThirdPartyDubboInterface thirdPartyDubboInterface;

    /**
     * 发送验证码
     *
     * @param phoneNum 手机号
     */
    @Override
    public void sendCode(String phoneNum) {
        // 先看看redis中是否已经存在一个同手机号的验证码
        String oldCode = stringRedisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + phoneNum);
        if (!StringUtils.isEmpty(oldCode)) {
            // 如果已经存在，把这个验证码的时间拿出来
            long oldTime = Long.parseLong(oldCode.split("_")[1]);
            if (System.currentTimeMillis() - oldTime < 60000) {
                // 如果是在60秒内重复发送验证码，就不准再发
                throw new RRException(BizCodeEnum.SMS_REPEAT_EXCEPTION.getMessage(), BizCodeEnum.SMS_REPEAT_EXCEPTION.getCode());
            }
        }

        // 生成验证码
        String code = UUID.randomUUID().toString().substring(0, 5);
        // redis存放值，key就是 sms:code:手机号，值就是验证码_当前系统时间
        stringRedisTemplate.opsForValue().set(
                AuthConstant.SMS_CODE_CACHE_PREFIX + phoneNum,
                code + "_" + System.currentTimeMillis(),
                AuthConstant.SMS_CODE_EXPIRE_TIME,
                AuthConstant.SMS_CODE_EXPIRE_UNIT);

        // Dubbo 调用
        R smsCodeRegisterR = thirdPartyDubboInterface.sendSMSCode(phoneNum, code, AuthConstant.SMS_CODE_EXPIRE_TIME, ThirdPartyConstant.SMS_CODE_REGISTER);
        if (smsCodeRegisterR.getCode() != 0) {
            throw new RRException(smsCodeRegisterR.getMsg(), smsCodeRegisterR.getCode());
        }
    }

    /**
     * 验证验证码
     *
     * @param phoneNum 手机号
     * @param code     验证码
     */
    @Override
    public void verifyCode(String phoneNum, String code) {
        String redisCode = stringRedisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + phoneNum);
        if (StringUtils.isEmpty(redisCode)) {
            throw new RRException(BizCodeEnum.INVALID_MSG_CODE.getMessage(), BizCodeEnum.INVALID_MSG_CODE.getCode());
        } else {
            redisCode = redisCode.split("_")[0];
            if (!redisCode.equals(code)) {
                throw new RRException(BizCodeEnum.ERROR_MSG_CODE.getMessage(), BizCodeEnum.ERROR_MSG_CODE.getCode());
            }
        }
    }

    /**
     * 用户注册
     *
     * @param userRegisterVo 注册信息Vo
     */
    @Override
    public void register(UserRegisterVo userRegisterVo) {
        // Dubbo调用:
        RegisterMemberTo registerMemberTo = new RegisterMemberTo();
        registerMemberTo.setUsername(userRegisterVo.getUsername());
        registerMemberTo.setPassword(userRegisterVo.getPassword());
        registerMemberTo.setPhoneNum(userRegisterVo.getPhoneNum());
        R registerR = memberDubboInterface.register(registerMemberTo);

        if (registerR.getCode() == 0) {
            // 远程接口调用成功
            // 删除redis中用过的验证码，并把姓名和手机号存到ES
            stringRedisTemplate.delete(AuthConstant.SMS_CODE_CACHE_PREFIX + userRegisterVo.getPhoneNum());
            RegisterUpTo registerUpTo = new RegisterUpTo();
            registerUpTo.setUsername(userRegisterVo.getUsername());
            registerUpTo.setPhoneNum(userRegisterVo.getPhoneNum());

            // Dubbo 调用
            R upResultR = searchDubboInterface.registerUpToES(registerUpTo);
            if (upResultR.getCode() != 0) {
                throw new RRException(upResultR.getMsg(), upResultR.getCode());
            }
        } else {
            throw new RRException(registerR.getMsg(), registerR.getCode());
        }
    }

    /**
     * 检查用户名是否重复
     *
     * @param username 用户名
     */
    @Override
    public void checkUserName(String username) {
        // Dubbo 调用
        R uniqueResultR = searchDubboInterface.usernameUniqueES(username);
        if (uniqueResultR.getCode() != 0) {
            throw new RRException(uniqueResultR.getMsg(), uniqueResultR.getCode());
        }
    }
}
